import {_decorator, ccenum, CCFloat, Component, Node, UITransform, v3, Vec3} from 'cc';
import {Constant} from '../../config/Constant';
import {ActorActionManager} from '../../framework/manager/ActorActionManager';
import {logUtil} from "../../framework/util/logUtil";
import {ProjectileEmitter} from '../projectile/ProjectileEmiter';
import {LevelCon} from './LevelCon';
import {AudioManager} from "../../framework/manager/AudioManager";
import {Projectile} from "../projectile/Projectile";

const {ccclass,  property} = _decorator;

//攻击职业
export enum AttackType {
    Melee = 0, // 近战
    Range = 1, // 远程
    Blaster =2, //爆破手
}

//核心是数据处理
ccenum(AttackType)
@ccclass('PlayerCon')
export class PlayerCon extends Component {
    //状态管理器
    actor: ActorActionManager | null = null;

    //日志控制器
    log = logUtil.instance
    logLevel = "PlayerCon"

    //终点方向
    destForward: Vec3

    //锁定的敌人
    target: ActorActionManager | null = null;

    //攻击距离:默认加上一半精灵width
    @property(CCFloat)
    attackRange: number = 500;

    //视距:默认加上一半精灵width
    @property(CCFloat)
    fov: number = 500;

    //避障距离:按道理是(精灵width+target.width)/2
    @property(CCFloat)
    vo: number = 500;

    //势力
    regime: string;

    //职业
    @property({type: AttackType})
    career: AttackType = AttackType.Melee;

    //远程投射器
    projectileEmitter: ProjectileEmitter;

    start() {
        this.log.log(this.logLevel, `start`)
        // this.actor = this.node.getComponent(ActorActionManager);

        let uiTransform = this.node.getComponent(UITransform).width

        //设置优先级:预制体>start>预设置
        this.fov += uiTransform / 2
        this.attackRange += uiTransform / 2

        this.node.on(Constant.ACOTR_EVENT_NAME.onKilled, this.onKilled, this)
        this.node.on(Constant.ACOTR_EVENT_NAME.onFrameAttack, this.onFrameAttack, this);
    }

    update(dt: number) {
        this.executeAI()
    }

    onDestroy() {
        this.log.log(this.logLevel, `onDestroy`)
        this.node.off(Constant.ACOTR_EVENT_NAME.onKilled, this.onKilled, this);
        this.node.off(Constant.ACOTR_EVENT_NAME.onFrameAttack, this.onFrameAttack, this);
    }

    /**
     * 人机思路_(调度时间和方式)
     */
    executeAI() {
        this.log.log(this.logLevel, `${this.node.uuid}节点数据{
            fov:${this.fov},attackRange:${this.attackRange},vo:${this.vo},
            worldPosition:${this.node.worldPosition},阵营:${this.regime}}`
        )
        if (!this.checkAndAttack())
            this.moveToEndPoint()

    }

    //region 行为定义
    /**
     * 搜索最近的敌人
     */
    getNeareastEnemy(): Node | null {

        let nearastEnemy: Node = this.discoverUnitsInRange(this.findEnemies(), this.fov)

        if (nearastEnemy) {
            this.target = nearastEnemy.getComponent(ActorActionManager)
            this.log.log(this.logLevel, `getNeareastEnemy ${this.node.uuid}找到敌人${nearastEnemy.uuid}`)
            return nearastEnemy
        }
        this.log.log(this.logLevel, `getNeareastEnemy ${this.node.uuid}未找到敌人`)
        return null;
    }

    /**
     * 检索敌人并进攻
     */
    checkAndAttack(): boolean {
        // 查找面前是否有怪物
        let enemy = this.getNeareastEnemy()
        if (enemy) {
            // 敌人距离:判断是否在攻击范围内
            const distance = Vec3.distance(this.node.worldPosition, enemy.worldPosition);
            if (distance > this.fov) {
                //前往,视距>精灵图长度无须避障
                // this.log.log("ORCA", `${this.logLevel}前往{节点id:${this.node.uuid},距离:${distance},}`)

            } else if (distance <= this.attackRange) {
                //进攻
                // this.log.log("ORCA", `${this.logLevel}进攻{节点id:${this.node.uuid},距离:${distance},}`)
                this.actor.changeState(Constant.ACTION.Attack);
                return true
            } else {
                //追击
                this.log.log("ORCA", `${this.logLevel + 1}追击{
                    节点id:${this.node.uuid},距离:${distance},
                    enemy:${enemy.worldPosition},node:${this.node.worldPosition},
                }`)
                //无需避障进攻敌人
                if (distance >= this.attackRange+this.vo||this.ORCA(enemy.worldPosition)){
                    this.log.log("ORCA", `无需避障进攻敌人{节点id:${this.node.uuid},距离:${distance},}`)
                    this.setDestinationAndMove(enemy.worldPosition);
                }
                return true
            }
        }
        return false;
    }

    /**
     * vo避障
     */
    ORCA(enemy) {
        // this.log.log("ORCA", `${this.logLevel}:ORCA`)
        let nearastEnemy: Node = this.discoverUnitsInRange(this.findAllies(), this.attackRange)

        //发现避障目标,进行处理
        if (nearastEnemy) {
            //碰撞策略:势力1:上移目标
            let ORCAdirectionX = this.regime == Constant.DYNAMIC_RESOURCE.Actor.Forces1.Regime ? this.vo : -this.vo;
            let ORCAdirectionY = this.vo;

            switch (this.actor.data.career) {
                case 0://近战
                    if(this.regime == Constant.DYNAMIC_RESOURCE.Actor.Forces1.Regime){
                        if(enemy.x>this.node.worldPosition.x){
                            ORCAdirectionX=ORCAdirectionX*Math.random()*3;
                        }else{
                            ORCAdirectionX=-ORCAdirectionX;
                        }
                    }
                case 1://弓手
                    ORCAdirectionY=ORCAdirectionY*Math.random()*2;
                    break;
                default://爆炸
                    break;
            }
            let destTempForward = v3(this.node.worldPosition.x + ORCAdirectionX,
                (this.node.worldPosition.y + ORCAdirectionY) * (Math.random() < 0.5 ? -1 : 1),
                this.node.worldPosition.z)

            this.setDestinationAndMove(destTempForward);

            this.log.log("ORCA", `${this.logLevel + 2}开始避障{
            节点id:${this.node.uuid},目标方向:${this.actor.destForward}
            fov:${this.fov},attackRange:${this.attackRange},vo:${this.vo},位置:${this.node.worldPosition}
            }`)

            return false;
        }

        //无需避障
        return true
    }

    /**
     * 前往终点
     */
    moveToEndPoint() {
        this.log.log(this.logLevel, `moveToEndPoint 下当前x位置:${this.node.worldPosition.x},${this.destForward.x}`)
        this.setDestinationAndMove(this.destForward);
    }

    onFrameAttack() {
        this.log.log("fight", `${this.node.name+this.node.uuid}触发攻击动画帧`)
        AudioManager.instance.playSfx(this.actor.data.attackSfx);
        switch (this.career) {
            case AttackType.Range://远程
                //1.远程投射
                let projectile = this.projectileEmitter!.create();
                // 投射物位置,追踪信息
                projectile.node.worldPosition = this.node.worldPosition;
                projectile.target = this.target.node;
                projectile.host = this.node;
                projectile.fire();
                break;
            case AttackType.Blaster://爆破手
                //1.造成伤害
                this.target.hurt(this.actor.actorProperty.attack, this.actor,Constant.HURT_TYPE.Attack);
                //2.自己消失
                this.actor.hurt(this.actor.actorProperty.hp,this.actor,Constant.HURT_TYPE.SelfHit)
                break;
            default://近战
                //1.造成伤害
                this.target.hurt(this.actor.actorProperty.attack, this.actor,Constant.HURT_TYPE.Attack);
                break;
        }

    }

    findEnemies(): Array<Node> {
        return this.regime == Constant.DYNAMIC_RESOURCE.Actor.Forces1.Regime ?
            LevelCon.instance.forces2AutoActorCon?.enemies
            : LevelCon.instance.forces1AutoActorCon?.enemies
    }

    findAllies(): Array<Node> {
        return this.regime == Constant.DYNAMIC_RESOURCE.Actor.Forces1.Regime ?
            LevelCon.instance.forces1AutoActorCon?.enemies
            : LevelCon.instance.forces2AutoActorCon?.enemies
    }

    // 设置目标方向并移动
    private setDestinationAndMove(destination: Vec3) {
        Vec3.subtract(this.actor.destForward, destination, this.node.worldPosition);
        this.actor.destForward.normalize();
        this.actor.changeState(Constant.ACTION.Run);
    }

    /**
     * 获取最近的符合单位节点
     * @param {Array<Node>} units 单位群
     * @param {number} nearDistance 搜索范围
     * @return {Node|null} 返回最近的单位节点，如果没有找到则返回null
     */
    discoverUnitsInRange(units: Array<Node>, nearDistance: number): Node {
        this.log.log(this.logLevel, `discoverUnitsInRange ${this.node.uuid}搜索最近的单位`)
        let resultUnit: Node | null = null;

        if (!units || units?.length == 0) {
            this.log.log(this.logLevel, `discoverUnitsInRange ${this.node.uuid}单位群体未初始化`)
            return null;
        }
        let mindistance = 1300
        for (let unit of units) {
            if (unit.active == true && unit.uuid != this.node.uuid) {
                let distance = Vec3.distance(this.node.worldPosition, unit.worldPosition);
                if (distance < nearDistance && mindistance > distance) {
                    mindistance = distance
                    resultUnit = unit;
                }
            }
        }

        return resultUnit
    }

    onKilled() {
        /*
        对应势力对象池回收
        "碰撞销毁需要延迟1帧":https://forum.cocos.org/t/topic/144566/27*/
        this.scheduleOnce(() => {
            //角色节点对象池回收
            if(this.regime == Constant.DYNAMIC_RESOURCE.Actor.Forces1.Regime){
                LevelCon.instance.forces1AutoActorCon?.enemyPools.free(this.node.name,this.node)
            }else{//敌人
                LevelCon.instance.forces2AutoActorCon?.enemyPools.free(this.node.name,this.node)
                //生成金币
                LevelCon.instance.coinCon.createCoin(this.node)
                //经验值
                LevelCon.instance.node.emit(Constant.EVENT_NAME.onExpUpdate,this.actor.data.cost)
            }

            let allies = this.findAllies()
            allies.splice(allies.indexOf(this.node), 1);

            this.node.active = false;
        }, 0.1)
    }

    //endregion
}
